<template>
  <div>
      <!-- 面包屑导航区域 -->
    <el-breadcrumb separator-class="el-icon-arrow-right">
        <el-breadcrumb-item :to="{ path: '/home' }">首页</el-breadcrumb-item>
        <el-breadcrumb-item>商品管理</el-breadcrumb-item>
        <el-breadcrumb-item>参数列表</el-breadcrumb-item>
    </el-breadcrumb>

    <!-- 卡片试图区域 -->
    <el-card>
      <!-- 警告区域 -->
      <el-row>
        <el-col>
          <el-alert
            :closable='false'
            title="注意：只允许第三级分类设置相关参数！"
            type="warning"
            show-icon>
          </el-alert>
        </el-col>
      </el-row>
      <!-- 选择商品分类区域 -->
      <el-row class="cat_opt">
        <el-col>
          <span>选择商品分类：</span>
          <!-- 选择商品分类的级联选择框 -->
          <el-cascader
            v-model="selectedCateKeys"
            :options="cateList"
            :props="cateProps"
            clearable
            @change="handleChange"></el-cascader>
        </el-col>
      </el-row>
      <!-- Tabs 标签分页 -->
      <!-- tab-click：Tab 页签点击事件处理函数(当我们点击不同页签时会触发) 
           v-model绑定的参数，会收集被激活的Tab-pane页签的name属性的值
           disabled: 是否被禁用 -->
           <!-- 动态参数：供用户选择的(如：商品颜色)
                静态属性：给用户观看的(如：商品生产日期) -->
      <el-tabs v-model="activeName" @tab-click="handleTabClick">
        <!-- 添加动态参数的面板 -->
        <el-tab-pane label="动态参数" name="many">
          <!-- 添加参数按钮 -->
          <el-button type="primary" :disabled='isBtnDisabled' size="mini" @click="adddialogVisible = true">添加参数</el-button>
          <!-- 动态参数表格 渲染manyTableData -->
          <el-table :data="manyTableData" border stripe>
             <!-- 展开行(该行数据来源于manyTableData) -->
              <el-table-column type="expand">
                <template slot-scope="scope">
                  <!-- 循环渲染tag标签 -->
                    <el-tag v-for="(item,i) in scope.row.attr_vals" :key="i"
                    :class="i===0 ? 'tag-maglft' :'left-tag'" closable @close='handleClose(i,scope.row)'>
                      {{item}}
                    </el-tag>
                    <!-- 最后的输入文本框 -->
                    <el-input
                      :class="scope.row.attr_vals.length===0 ? 'input-new-tag':'with'"
                      v-if="scope.row.inputVisible"
                      v-model="scope.row.inputValue"
                      ref="saveTagInput"
                      size="small"
                      @keyup.enter.native="handleInputConfirm(scope.row)"
                      @blur="handleInputConfirm(scope.row)"
                      >
                    </el-input>
                    <!-- 添加的按钮 -->
                <el-button v-else :class="scope.row.attr_vals.length===0 ? 'button-new-tag':'with'" size="small" @click="showInput(scope.row)">+ New Tag</el-button>

                </template>
              </el-table-column>
              <!-- 索引列 -->
              <el-table-column type="index"></el-table-column>
              <!-- 内容列 -->
              <el-table-column prop="attr_name" label="参数名称"></el-table-column>
              <el-table-column label="操作">
                <template slot-scope="scope">
                   <el-button type="primary" icon="el-icon-edit" size="mini" @click="showEditDialog(scope.row.attr_id)">编辑</el-button>
                   <el-button type="danger" icon="el-icon-delete" size=mini @click="removeParams(scope.row.attr_id)">删除</el-button>
                </template>
              </el-table-column>
          </el-table>
        </el-tab-pane>
        <!-- 添加静态属性的面板 -->
        <el-tab-pane label="静态属性" name="only">
          <!-- 添加属性按钮 -->
           <el-button type="primary" :disabled='isBtnDisabled' size="mini" @click="adddialogVisible = true">添加属性</el-button>
           <!-- 渲染静态属性表格 onlyTableData -->
            <el-table :data="onlyTableData" border stripe> 
              <!-- 展开行(该行数据来源于onlyTableData) -->
              <el-table-column type="expand">
                <template slot-scope="scope">
                  <!-- 循环渲染tag标签 -->
                    <el-tag v-for="(item,i) in scope.row.attr_vals" :key="i"
                    :class="i===0 ? 'tag-maglft' :'left-tag'" closable @close='handleClose(i,scope.row)'>
                      {{item}}
                    </el-tag>
                    <!-- 最后的输入文本框 -->
                    <el-input
                      :class="scope.row.attr_vals.length===0 ? 'input-new-tag':'with'"
                      v-if="scope.row.inputVisible"
                      v-model="scope.row.inputValue"
                      ref="saveTagInput"
                      size="small"
                      @keyup.enter.native="handleInputConfirm(scope.row)"
                      @blur="handleInputConfirm(scope.row)"
                      >
                    </el-input>
                    <!-- 添加的按钮 -->
                <el-button v-else :class="scope.row.attr_vals.length===0 ? 'button-new-tag':'with'" size="small" @click="showInput(scope.row)">+ New Tag</el-button>

                </template>
              </el-table-column>
              <!-- 索引列 -->
              <el-table-column type="index"></el-table-column>
              <!-- 内容列 -->
              <el-table-column prop="attr_name" label="属性名称"></el-table-column>
              <el-table-column label="操作">
                <template slot-scope="scope">
                   <el-button type="primary" icon="el-icon-edit" size="mini"  @click="showEditDialog(scope.row.attr_id)">编辑</el-button>
                   <el-button type="danger" icon="el-icon-delete" size=mini @click="removeParams(scope.row.attr_id)">删除</el-button>
                </template>
              </el-table-column>
          </el-table>
        </el-tab-pane>
      </el-tabs>
    </el-card>

    <!-- 添加参数对话框(动态静态共用一个) -->
    <el-dialog
      :title="'添加'+titleText"
      :visible.sync="adddialogVisible"
      @close='addDialogClosed'
      width="50%">
      <!-- 添加参数的表单 -->
     <el-form :model="addFrom" :rules="addFromRules" ref="addFromRef" label-width="100px">
        <el-form-item :label="titleText" prop="attr_name">
          <el-input v-model="addFrom.attr_name"></el-input>
        </el-form-item>
     </el-form>
      <span slot="footer" class="dialog-footer">
        <el-button @click="adddialogVisible = false">取 消</el-button>
        <el-button type="primary" @click="addParams">确 定</el-button>
      </span>
    </el-dialog>


    <!-- 修改参数的对话框 -->
    <el-dialog
      :title="'修改'+titleText"
      :visible.sync="editdialogVisible"
      @close='editDialogClosed'
      width="50%">
      <!-- 修改参数的表单 -->
     <el-form :model="editFrom" :rules="addFromRules" ref="editFromRef" label-width="100px">
        <el-form-item :label="titleText" prop="attr_name">
          <el-input v-model="editFrom.attr_name"></el-input>
        </el-form-item>
     </el-form>
      <span slot="footer" class="dialog-footer">
        <el-button @click="editdialogVisible = false">取 消</el-button>
        <el-button type="primary" @click="editParams()">确 定</el-button>
      </span>
    </el-dialog>
  </div>
  <!-- el-table 表格中 prop：代表该行的数据来源
       el-from  表格中  prop：代表该el-form-item的验证规则
  -->
</template>

<script>
export default {
  data() {
    return {
      // 商品列表分类
        cateList:[],
      // 级联选择器的props配置项
        cateProps:{
                expandTrigger: 'hover', // 经过触发
                // key所对应的数据 皆来自cateList数组中的对象元素的属性
                value:'cat_id',  // 具体选中的属性的值
                label:'cat_name',  //  具体看到的属性的值(我们看到的是lable，但选中是value的值)
                children:'children', // 指定父子嵌套用的是哪个属性 
         },
        // 级联选择框所选中的id的值(被选中的1,2,3级都会有)
        selectedCateKeys:[],
        // activeName收集被激活的页签的name属性的值
        activeName:'many',
        // 获取到的动态参数的数据，其值会根据级联对话框的选择项的变化而不断改变
        // (这次装着 大家电111/电视/曲面电视的动态参数，当我们切换到 热门推荐/圣诞狂欢/护肤)
        // 又会装着 护肤 的动态参数(因为更具不同的分类id，我们请求到了不同的数据)
        manyTableData:[],
        // 获取到的静态属性的数据
        onlyTableData:[],
        // 控制添加属性、参数的对话框的显示于隐藏
        adddialogVisible:false,
        // 添加参数的表单数据对象
        addFrom:{
          attr_name:'',
        },
        // 添加表单的验证规则对象
        addFromRules:{
          attr_name:[{required:true,message:'请输入参数名称',trigger:'blur'}]
        },
        // 控制修改对话框的显示于隐藏
        editdialogVisible:false,
        // 编辑参数的表单数据对象
        editFrom:{//无需给属性，因为我们会将请求到的数据放入

        }, 
      }
  },
  created(){
    this.getCateList()
  },
  methods:{
    // 获取所有的商品分类，用于级联选择器
    async getCateList(){
      const {data:res} =  await this.$http.get(`categories`)
      if(res.meta.status !== 200){
        return this.$message.error('获取商品列表失败！')
      }
      this.cateList = res.data
    },
    // 级联选择框 每当我们：选中或切换选中项时，会触发的函数
    handleChange(){
     this.getParamsData()
    },
    // Tab 页签点击事件处理函数(当我们点击不同页签时会触发)
    handleTabClick(){
      // activeName随着页签的切换，收集的值页不断切换
      this.getParamsData()
    },
    // 获取参数的列表数据
    async getParamsData(){
       // 如果selectedCateKeys数组的长度 !==3 就代表我们选中的不是三级分类项
      // 那么是不允许的，不符合规定，我们就要将selectedCateKeys清空
      // 那么选中项就会被重置
      if(this.selectedCateKeys.length !== 3){
        this.selectedCateKeys = []
        this.manyTableData = []
        this.onlyTableData = []
        return
      } 
      // 证明选中的是三级分类选项的话
      // 根据所选分类的id(cateId)，和当前所处面板(activeName)，获取对应的三级商品的属性
      const {data:res} = await 
      this.$http.get(`categories/${this.cateId}/attributes`,
      {params:{sel:this.activeName}})
      if(res.meta.status !== 200){
          return this.$message.error('获取参数列表失败！')
      } 
      // 将被选中的第三级商品的所有属性遍历一遍
      // 找到attr_vals(里面包含了所有动态属性)
      // 并将动态属性 按照" " 分割成数组，用于显示为tag标签
      res.data.forEach((item) => {
         // 控制 tag标签添加的输入框和按钮的显示于隐藏
        item.inputVisible = false
         // 文本框中输入的内容
        item.inputValue = ''
          // 解决split分割空字符串 数组出现一个''元素 
        // 重新赋值，attr_vals属性改为数组
        if(item.attr_vals.length !==0){
            item.attr_vals =  item.attr_vals.split(' ')
        }else{ // 如果字符串为空，那么就直接赋值空数组
            item.attr_vals = []
        }
      });
        console.log(res.data);
      // 进行判断，获取到的是 动态的还是静态的数据
      if(this.activeName === 'many'){ // 动态参数
      // 如果是动态的就放到manyTableData中
      // 到时候动态标签页下，就渲染manyTableData中的数据
        this.manyTableData = res.data
      }else { 
      // 反之就是获取到的是静态数据放到onlyTableData
      // 到时候动态标签页下，就渲染onlyTableData中的数据
        this.onlyTableData = res.data
      }
    },
     // 监听对话框的关闭事件
    addDialogClosed(){
      // 重置表单
          this.$refs.addFromRef.resetFields()
    },
    // 添加参数对话框的确定按钮
    addParams(){
       // 根据该三级分类的id(cateId) 和 静态的还是动态的 activeName名称，以及要添加的att_name
       this.$refs.addFromRef.validate(async(valid)=>{
          if(!valid){ // 如果没有通过
            return
          }
          // 如果通过的话，就需要发起请求添加参数
        const {data:res} =  await this.$http.post(`categories/${this.cateId}/attributes`,
          {attr_name:this.addFrom.attr_name,attr_sel:this.activeName})
          if(res.meta.status !== 201){
            return this.$message.error('添加参数失败！')
          }
          // 重新刷新 参数表单列表,让manyTableData 或 onlyTableData获取到最新的数据
           this.getParamsData()
           this.adddialogVisible = false
          return this.$message.success('添加参数成功！')
       })
    },
    // 控制修改对话框的弹出
    async showEditDialog(attrId){ // 当前行的id为参数的id
    // 请求路径接收两个id：第一个：该三级商品分类的id，第二个：该编辑按钮所在行的id
      const {data:res} =  await this.$http.get(`categories/${this.cateId}/attributes/${attrId}`,{
        params:{attr_sel:this.activeName}
      })
      if(res.meta.status !== 200){
        return this.$message.error('获取参数信息失败！');
      }
      // 如果成功！,将数据放入 编辑表单
      this.editFrom = res.data

      this.editdialogVisible = true
    },
    // 监听编辑对话框的消失事件
    editDialogClosed(){
      // 重置编辑表单
        this.$refs.editFromRef.resetFields()
    },
    // 编辑对话框的确定按钮的点击事件
    editParams(){
        this.$refs.editFromRef.validate(async(valid)=>{
          if(!valid){ // 如果没有通过
            return
          }
          // 如果通过的话，就需要发起请求添加参数
        const {data:res} =  await this.$http.put(`categories/${this.cateId}/attributes/${this.editFrom.attr_id}`,
          {attr_name:this.editFrom.attr_name,attr_sel:this.activeName})
          if(res.meta.status !== 200){
            return this.$message.error('修改参数失败！')
           }
          //  如果修改成功！
            this.$message.success('修改参数成功！')
            this.getParamsData()
            this.editdialogVisible = false
        })
     },
    // 删除按钮(获取该行的id(attr_id)以及三级商品的id) 
    async removeParams(attr_id){
        const confirmResult =  await this.$confirm('是否删除该商品参数?', '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
          }).catch(err=>{return err})   
          if(confirmResult === 'cancel'){
            return this.$message('已取消删除')
          }
          // 如果选择删除！
          const {data:res} =  await this.$http.delete(`categories/${this.cateId}/attributes/${attr_id}`)
          if(res.meta.status !== 200){
            return this.$message.error('删除参数失败！')
           }
          //  刷新参数列表
          this.$message.success('删除商品参数成功')
          this.getParamsData();
     },
    //  点击tag标签，将input框显示
     showInput(row){
      row.inputVisible = true
      // 调用nextTick生命函数(在下一次 DOM 更新结束后执行其指定的回调)，
      // 让刚出现的input获取焦点
      this.$nextTick(()=>{
       this.$refs.saveTagInput.focus();
      })
     },
    //  input输入完毕后 回车和离焦 事件
    async handleInputConfirm(row){
      // 再回车或离焦之后
      // 添加输入的inputValue，再控制inputVisible=false
      // input消失，button显示
      if(row.inputValue.trim().length ===0){
        row.inputValue = ''
        row.inputVisible = false
        return 
      }
        row.attr_vals.push(row.inputValue.trim());
        row.inputValue = ''
        row.inputVisible = false
        // 需要发起请求，保存这一次操作
        const {data:res} = await this.$http.put(`categories/${this.cateId}/attributes/${row.attr_id}`
        ,{attr_name: row.attr_name, attr_sel: row.attr_sel, attr_vals: row.attr_vals.join(" ")})

        if(res.meta.status !== 200){
          return this.$message.error('添加标签失败！')
        }
        // 不需要再刷新列表，因为我们将显示数据已经放置在 attr_vals 数组中
        // 渲染的也是 attr_vals数组，当页面再次刷新时，会将数组再次放入数据库
        this.$message.success('添加标签成功！')
     },
    //  tag标签删除按钮事件(根据索引再数组中删除，再将数组发送请求到数据库)
     async handleClose(index,row){
          const confirmResult =  await this.$confirm('是否删除该标签?', '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
          }).catch(err=>{return err})   

          if(confirmResult === 'cancel'){
            return this.$message('已取消删除')
          }
          row.attr_vals.splice(index,1)
          // 如果选择删除！
         const {data:res} =  await this.$http.put(`categories/${this.cateId}/attributes/${row.attr_id}`,
         {attr_name: row.attr_name, attr_sel: row.attr_sel, attr_vals: row.attr_vals.join(" ")})
         if(res.meta.status !== 200){
            return this.$message.error('删除参数失败！')
          }
         this.$message.success('删除标签成功！')
      }
  },
  computed:{
    // 用于控制按钮的禁用(如果按钮需要被禁用，则返回true，否则返回fales)
    isBtnDisabled(){
      // 如果数组selectedCateKeys.length !== 3,就代表没选中三级商品分类
      // 那么返回true，禁用
      return this.selectedCateKeys.length === 3 ? false : true 
    },
    // 获取当前三级分类的id
    cateId(){
      if(this.selectedCateKeys.length ===3 ){
        return this.selectedCateKeys[2]
      }else{
        return null
      }
    },
    // 动态计算标题的文本
    titleText(){
        if(this.activeName === 'only'){
          return "静态属性"
        }else{
          return "动态参数"
        }
    }
  }
}
</script>

<style scoped lang='less'>
.cat_opt{
  margin: 15px 0;
}
.input-new-tag,.button-new-tag{
  width: 120px;
  margin-left: 50px;
}
.left-tag{
  margin-left: 10px;
}
.with {
  width: 120px;
}
.el-tag{
  margin: 10px;
}
.tag-maglft{
  margin-left: 50px;
}
</style>